/*
 * Copyright (c) 2016-2017, Guangshan (guangshan1992@qq.com) and the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yueyang.sojourn.server.service.wx;

import com.alibaba.fastjson.JSONObject;
import com.yueyang.sojourn.server.common.JsonUtils;
import com.yueyang.sojourn.server.common.consts.Constants;
import com.yueyang.sojourn.server.config.QiniuProperties;
import com.yueyang.sojourn.server.model.vo.UploadResult;
import com.yueyang.sojourn.server.service.FileService;
import com.yueyang.sojourn.server.service.wx.model.WxAccessToken;
import com.yueyang.sojourn.server.service.wx.model.WxSessionKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * FastBootWeixin WxServer
 * 注意拦截调用异常，如果是token过期，重新获取token并重试
 *
 * @author Guangshan
 * @date 2017/7/23 17:14
 * @since 0.1.2
 */
@Component
@Slf4j
public class WxServer {
    @Autowired
    private FileService fileService;
    @Resource
    private QiniuProperties qiniuProperties;
    @Autowired
    private RedisTemplate redisTemplate;

    private final RestTemplate restTemplate;

    private static final String WX_CODE_SESSION_URL = "https://api.weixin.qq.com/sns/jscode2session";
    //生成微信分享二维码
    private static final String WX_SHARE_QRCODE_URL = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";

    private static final String WX_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";

    private static final String REDIS_WX_TOKEN_KEY= "42";
    @Value("${wx.app-id}")
    private String appid;

    @Value("${wx.app-secret}")
    private String appSecret;

    public WxServer() {
        this.restTemplate = new RestTemplate();
    }

    public WxSessionKey getSessionKey(String code) {
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(WX_CODE_SESSION_URL)
                .queryParam("appid", appid)
                .queryParam("secret", appSecret)
                .queryParam("js_code", code)
                .queryParam("grant_type", "authorization_code");
        String json = restTemplate.getForObject(builder.toUriString(), String.class);
        log.info("微信返回json:{}", json);
        WxSessionKey wxSessionKey = JsonUtils.parseObject(json, WxSessionKey.class);
        return wxSessionKey;
    }

    public WxAccessToken getAccessToken() {
        WxAccessToken wxAccessToken = (WxAccessToken) redisTemplate.opsForValue().get(Constants.WX_ACCESS_TOKEN_KEY);
        if (wxAccessToken == null) {
            wxAccessToken = createAccessToken();
            redisTemplate.opsForValue().setIfAbsent(Constants.WX_ACCESS_TOKEN_KEY, wxAccessToken, wxAccessToken.getExpiresIn() * 3 / 4, TimeUnit.SECONDS);
        }
        return wxAccessToken;
    }

    private WxAccessToken createAccessToken() {
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(WX_ACCESS_TOKEN_URL)
                .queryParam("appid", appid)
                .queryParam("secret", appSecret)
                .queryParam("grant_type", "client_credential");
        String json = restTemplate.getForObject(builder.toUriString(), String.class);
        log.info("微信返回json:{}", json);
        WxAccessToken wxAccessToken = JsonUtils.parseObject(json, WxAccessToken.class);
        return wxAccessToken;
    }

    /**
     * 获取分享二维码
     * @param userId  用户id
     * @param pagePath 页面路径
     * @param width  二维码宽度
     * @param scene 自定义参数 最大32个可见字符，只支持数字，大小写英文以及部分特殊字符：!#$&'()*+,/:;=?@-._~，其它字符请自行编码为合法字符
     * @return
     */
    public UploadResult getAcode(Long userId, String pagePath, Long width,  String scene) {
        UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(WX_SHARE_QRCODE_URL)
                .queryParam("access_token", getAccessToken().getAccessToken());

        HttpHeaders httpHeaders = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json;charset=UTF-8");
        httpHeaders.setContentType(type);
        Map<String, Object> paramsJson = new HashMap();
        paramsJson.put("scene", scene);
        paramsJson.put("page", pagePath);
        paramsJson.put("width", width);
        HttpEntity<Map<String, Object>> objectHttpEntity = new HttpEntity<>(paramsJson,httpHeaders);
        ResponseEntity<ByteArrayResource> result = restTemplate.postForEntity(builder.toUriString(), objectHttpEntity, ByteArrayResource.class);
        String contentType = result.getHeaders().get("Content-Type").stream().findFirst().orElse("");
        String suffix = "."+ contentType.substring(contentType.lastIndexOf("/") + 1);
        UploadResult uploadResult = fileService.upload(userId, qiniuProperties.getStorage().getAccessKey(), qiniuProperties.getStorage().getSecretKey(), qiniuProperties.getStorage().getBucket(), result.getBody().getByteArray(), "tmp_" + UUID.randomUUID().toString() + suffix);
        return uploadResult;
    }

}
